#include "Entity.h"

#include "Constraint.h"
#include "Game.h"

CEntity::CEntity(String sName, Vector vPos, String sTextureName, RGBAColor rgbaColor)
 : m_pPhysics(0), m_pSprite(0)
{
    init(sName, vPos, sTextureName, rgbaColor);
}

void CEntity::init(String sName, Vector vPos, String sTextureName, RGBAColor rgbaColor)
{
    
    m_sName = sName;
    m_bIsOnGround = false;
    //m_pAlignedWith = 0;
    
    //Get the full texture path
    const char* cpFilename = (CGame::getInstance()->getModPath() 
            + ENTITIES_PATH 
            + sTextureName 
            + TEXTURE_EXT)
            .c_str();
    
    //Create components
    //TODO: Work out this with constructors of CPhysicsBody and CPoint
    m_pPhysics = CGame::getInstance()->getWorld()->addPhysicsPoint(vPos);
    m_pSprite = new CSprite(cpFilename, rgbaColor);
    
    //TODO: Load these from rules file in current mod directory
    m_fCollisionRadius = 16.f;
    
}

void CEntity::update(Scalar fTimeStep)
{
    
    //Rotate the entity to align it with the aligned constraint
    if (m_pAlignedWith.isSet())
        this->getAngle() = -m_pAlignedWith.getAngle() - PI;
    
    //Apply gravity
    //if (!m_bIsOnGround)
        applyForce(Vector(0.f, -0.03));
        
    //CD
    //Integrate
    //m_pPhysics->integrate(fTimeStep);
    
    m_bIsOnGround = false;
    
    //Reset the facing vector so that we know we havn't calculated it yet
    m_vFacing.zero();
    
}

void CEntity::draw()
{
    
    //Animate
    //Render
    
    glPushMatrix();
        
        glTranslatef(getPos()[0], getPos()[1], 0.f);
        glRotatef(-getAngle() RAD_TO_DEG, 0.f, 0.f, 1.f);
        
        Scalar fScale = 1.f;//15.f/32.f;
        
        glScalef(fScale, fScale, 1.f);
        
        m_pSprite->render();
        
    glPopMatrix();
    
}

void CEntity::cleanup()
{
    delete m_pSprite;
    m_pSprite = 0;
    //NOTE: m_pPhysics is deleted by CWorld because it created it
    //delete m_pPhysics;
    m_pPhysics = 0;
}

void CEntity::collideEntities(CEntity* ent1, CEntity* ent2)
{
    
    Vector vBetween = ent2->getPos() - ent1->getPos();
    Scalar fDist2 = vBetween.getLength2();
    Scalar fMinDist = ent1->getCollisionRadius() + ent2->getCollisionRadius();
    
    //Check if the entities have collided
    if (fDist2 < fMinDist) {
        
        
        
    }
    //if both entities are solid
    //collide entities physically
    //inform entities of collision
    
}

void CEntity::alignWith(CSegment pSegment)
{
    
    m_pAlignedWith = pSegment;
    
}

/*Vector CEntity::countCollisionPixels(CEntity& ent1, CEntity& ent2, int iXOffset, int iYOffset)
{
    
    //TODO: Think about coordinate centered pixels
    
    int iEnt1PosX = (int)ent1.getPos()[0]; int iEnt1PosY = (int)ent1.getPos()[1];
    int iEnt2PosX = (int)ent2.getPos()[0] + iXOffset; int iEnt2PosY = (int)ent2.getPos()[1] + iYOffset;
    
    int x1 = CMath::getMax(iEnt1PosX, iEnt2PosX);
    int x2 = CMath::getMin(iEnt1PosX + ent1.getWidth(), iEnt2PosX + ent2.getWidth());
    
    int y1 = CMath::getMax(iEnt1PosY, iEnt2PosY);
    int y2 = CMath::getMin(iEnt1PosY + ent1.getHeight(), iEnt2PosY + ent2.getHeight());
    
    long* iEnt1MaskData = ent1.getSprite().getMaskData();
    long* iEnt2MaskData = ent2.getSprite().getMaskData();
    
    int iPixelCount = 0;
    
    for (int y = y1; y < y2; ++y)
    {
        for (int x = x1; x < x2; ++x)
        {
            
            int iAverageX=0;
            int iAverageY=0;
            
            //Check if both sprites have non-zero value pixels at this location
            //TODO: Make sure that bad array references don't occur
            if ( iEnt1MaskData[ (x - iEnt1PosX) + (y - iEnt1PosY) * ent1.getWidth() ]  &&
                iEnt2MaskData[ (x - iEnt2PosX) + (y - iEnt2PosY) * ent2.getWidth() ] ) {
                    
                    ++iPixelCount;
                    
                    iAverageX += x;
                    iAverageY += y;
                    
                }
            
        }
    }
    
    if (0 == iPixelCount)
        return Vector(1.f/0.f, 1.f/0.f);        //Return infinity if no collision
    return Vector(iAverageX / iPixelCount, iAverageY / iPixelCount);
    
}

Vector CEntity::findCollisionPoint(CEntity& ent1, CEntity& ent2, int iXOffset, int iYOffset)
{
    
    //TODO: Think about coordinate centered pixels
    
    int iEnt1PosX = (int)ent1.getPos()[0]; int iEnt1PosY = (int)ent1.getPos()[1];
    int iEnt2PosX = (int)ent2.getPos()[0] + iXOffset; int iEnt2PosY = (int)ent2.getPos()[1] + iYOffset;
    
    int x1 = CMath::getMax(iEnt1PosX, iEnt2PosX);
    int x2 = CMath::getMin(iEnt1PosX + ent1.getWidth(), iEnt2PosX + ent2.getWidth());
    
    int y1 = CMath::getMax(iEnt1PosY, iEnt2PosY);
    int y2 = CMath::getMin(iEnt1PosY + ent1.getHeight(), iEnt2PosY + ent2.getHeight());
    
    long* iEnt1MaskData = ent1.getSprite().getMaskData();
    long* iEnt2MaskData = ent2.getSprite().getMaskData();
    
    int iPixelCount = 0;
    
    for (int y = y1; y < y2; ++y)
    {
        for (int x = x1; x < x2; ++x)
        {
            
            int iAverageX=0;
            int iAverageY=0;
            
            //Check if both sprites have non-zero value pixels at this location
            //TODO: Make sure that bad array references don't occur
            if ( iEnt1MaskData[ (x - iEnt1PosX) + (y - iEnt1PosY) * ent1.getWidth() ]  &&
                iEnt2MaskData[ (x - iEnt2PosX) + (y - iEnt2PosY) * ent2.getWidth() ] ) {
                    
                    ++iPixelCount;
                    
                    iAverageX += x;
                    iAverageY += y;
                    
                }
            
        }
    }
    
    if (0 == iPixelCount)
        return Vector(1.f/0.f, 1.f/0.f);        //Return infinity if no collision
    return Vector(iAverageX / iPixelCount, iAverageY / iPixelCount);
    
}*/
